/*
 * File:   main.cpp
 * Author: user
 *
 * Created on July 22, 2014, 9:17 PM
 */
#include <cstdlib>
#include <iostream>
#include <sstream>
#include <string>
#include <stdio.h>
#include <sqlite3.h>
#include <iomanip>
#include <time.h>
#include "User.h"
#include "Administrator.h"
#include "Lecturer.h"
#include "Candidate.h"
#include "ExamTopic.h"
#include "TestQuestion.h"
#include "TestMain.h"


using namespace std;

int _loginAcctType(-1);
bool _isExitProgram(false);
void userLogin();
User* _user;
bool createDefaultDBAndTables();

int main(int argc, char *argv[]) 
{ 
    // only Authorized user can access to FBS
    while(1)
    {
        //system("clear");
        cout << "======================================================" << endl;
        cout << "Welcome to Test Management System (TMS)!" << endl;
        cout << "======================================================" << endl << endl ;
        cout << "1) Admin Login" << endl;
        cout << "2) Lecturer Login" << endl;
        cout << "3) Candidate Login" << endl;
        cout << "4) Create default DB and tables" << endl;
        cout << "5) Auto test" << endl;
        cout << "0  Quit program" << endl << endl;
        
        cout << "Please enter your choice: ";
        
        string selection;
        getline(cin, selection);
            
        if (!isdigit(selection[0])) 
        {
            cout << "Invalid input. Please try again" << endl;
            continue;
        }
            
        int iSelection;
        stringstream ss (selection);
        ss >> iSelection;
        
        switch (iSelection)
        {
            case 1: //Admin login
            {
                _user = new Administrator();
                break;
            }
            case 2: //Lecturer login
            {
                _user = new Lecturer();
                break;
            }
            case 3: //Candidate login
            {
                _user = new Candidate();
                break;
            }
            case 4: //Create Default DBA nd Tables
            {
                createDefaultDBAndTables();
                break;
            }
            case 5: //Run unit test
            {
                TestMain unitTest;
                system("clear");
                cout << endl << "[Auto Test]" << endl;
                unitTest.testmain();
                cout << endl;
                break;
            }
            case 0:
            {
                cout << "[-----Quit program-----]" << endl;
                cout << "Are you sure want to exit? (Y/N): ";
                string ans;
                getline(cin, ans);
                while(ans!="Y" && ans != "N")
                {
                    cout << "Invalid input!!!" << endl;
                    cout << "Are you sure want to exit? (Y/N): ";
                    getline(cin, ans);
                }
                if (ans == "Y")
                    exit(0);
                break;
            }
            default:
            {
                cout << "Invalid input. Please try again"<< endl << endl;
                break;
            }
        }
        
        if (iSelection < 4) //user Login
        {
            cout << endl;
            userLogin();
        }
           
    }
    
    return 0;
}

void userLogin()
{

    if (_loginAcctType < 0)
        _loginAcctType = _user->login();  
        
    if (_loginAcctType < 0)
    {
        cout << "Login failed." << endl;
        cout << "Maximum login attempts reached. Please contact system administrator" << endl << endl;
    }
    else
    {
        while(_loginAcctType != -1)
        {
            _user->printMenu();     

            cout << "Please enter your choice: ";
            
            string selection;
            getline(cin, selection);
            
            if (!isdigit(selection[0])) 
            {
                cout << "Invalid input. Please try again" << endl;
                continue;
            }

            int iSelection;
            stringstream ss (selection);
            ss >> iSelection;

            //run certain function based on user input
            bool isValid = _user->menuAction(iSelection,_isExitProgram,_loginAcctType);
            if (_isExitProgram)
                exit(0);
            if (!isValid)
            {
                cout << "Invalid input. Please try again" << endl;
            }
        }
    }
}

bool createDefaultDBAndTables()
{
    system("clear");
    cout << "[-----Create default database and tables-----]"<< endl;

    sqlite3 *db;
    char *zErrMsg = 0;
    int  rc;
    char *sql;

    /* Open database */
    rc = sqlite3_open("CSCI222_A2.db", &db);
    if( rc ){
       fprintf(stderr, "Can't open database: %s\n\n", sqlite3_errmsg(db));
       return false;
    }else{
       fprintf(stdout, "\nOpened database successfully\n");
    }

    // Create LoginACcount table
    sql = sqlite3_mprintf("CREATE TABLE LoginAccount(" \
            "ID             INTEGER    PRIMARY KEY   AUTOINCREMENT,"\  
            "UserID         CHAR(20)   UNIQUE NOT NULL," \
            "LoginID        CHAR(20)   UNIQUE          NOT NULL," \
            "LoginPassword  CHAR(20)   NOT NULL," \
            "AccountType    INT        NOT NULL," \
            "CreateBy       CHAR(20)   NOT NULL);");
    // Execute SQL statement 
    rc = sqlite3_exec(db, sql, 0, 0, &zErrMsg);
    if( rc != SQLITE_OK )
    {
        fprintf(stderr, "SQL error: %s\n\n", zErrMsg);
        sqlite3_free(zErrMsg);
        return false;
    }
    else
    {
        fprintf(stdout, "\nLoginAccount Table created successfully\n");
        User* sys;
        sys = new Administrator("System",-1);
        //Insert Admin, lecturer and candidate
        sys->addAccount("Admin001","Admin","admin",0,"System"); 
        sys->addAccount("Lecturer001","lect1","1234",1,"Admin001"); 
        sys->addAccount("Candidate001","c1","4321",2,"Lecturer001");
    }
    
    // Create LoginACcount table
    Lecturer lecturer("Lecturer001");
    sql = sqlite3_mprintf("CREATE TABLE ExamTopic(" \
            "ID            INTEGER          PRIMARY KEY      AUTOINCREMENT," \
            "ExamTopic     VARCHAR(1024)    UNIQUE  NOT NULL," \
            "Description   VARCHAR(1024)    NOT NULL,"\
            "CreateBy      VARCHAR(20)      NOT NULL);");
    /* Execute SQL statement */
    rc = sqlite3_exec(db, sql, 0, 0, &zErrMsg);
    if( rc != SQLITE_OK )
    {
        fprintf(stderr, "SQL error: %s\n\n", zErrMsg);
        sqlite3_free(zErrMsg);
        return false;
    }
    else
    {
        fprintf(stdout, "\nExamTopic table created successfully\n");
        //Insert Exam topic
        lecturer.addExamTopic("CSCI222-Test1","Total 5 MCQ, 1 mark for each","Lecturer001");
        lecturer.addExamTopic("CSCI222-Test2","Total 5 MCQ, 1 mark for each","Lecturer001");
    }
    
    
    
    // Create Question table
    sql = sqlite3_mprintf("CREATE TABLE Question(" \
            "ID         INTEGER    PRIMARY KEY   AUTOINCREMENT,"\  
            "Question   VARCHAR(2048)   NOT NULL," \
            "a          VARCHAR(2048)   NOT NULL," \
            "b          VARCHAR(2048)   NOT NULL," \
            "c          VARCHAR(2048)   NOT NULL," \
            "d          VARCHAR(2048)   NOT NULL," \
            "Answer     CHAR(10)        NOT NULL," \
            "ExamTopic  CHAR(20)        NOT NULL);");
    // Execute SQL statement 
    rc = sqlite3_exec(db, sql, 0, 0, &zErrMsg);
    if( rc != SQLITE_OK )
    {
        fprintf(stderr, "SQL error: %s\n\n", zErrMsg);
        sqlite3_free(zErrMsg);
        return false;
    }
    else
    {
        fprintf(stdout, "\nQuestion Table created successfully\n");
        //Insert test question
        string sel[] = {"choice a....","choice b....","choice c....","choice d...."};
        vector<string> selections(sel,sel+4);
        ExamTopic examTopic1;
        examTopic1.setTopic("CSCI222-Test1");
        examTopic1.addQuestion(TestQuestion("Q1",selections,"a"));
        examTopic1.addQuestion(TestQuestion("Q2",selections,"b"));
        examTopic1.addQuestion(TestQuestion("Q3",selections,"c"));
        examTopic1.addQuestion(TestQuestion("Q4",selections,"d"));
        examTopic1.addQuestion(TestQuestion("Q5",selections,"a"));
        lecturer.setExamTopic(examTopic1);
        lecturer.addQuestion2ExamTopic();
        
        ExamTopic examTopic2;
        examTopic2.setTopic("CSCI222-Test2");
        examTopic2.addQuestion(TestQuestion("Q1",selections,"d"));
        examTopic2.addQuestion(TestQuestion("Q2",selections,"c"));
        examTopic2.addQuestion(TestQuestion("Q3",selections,"b"));
        examTopic2.addQuestion(TestQuestion("Q4",selections,"a"));
        examTopic2.addQuestion(TestQuestion("Q5",selections,"a"));
        lecturer.setExamTopic(examTopic2);
        lecturer.addQuestion2ExamTopic();
    }
    
    // Create Test table
    sql = sqlite3_mprintf("CREATE TABLE TestSummary(" \
            "ID             INTEGER         PRIMARY KEY     AUTOINCREMENT," \  
            "ExamTopic      VARCHAR(2048)   NOT NULL," \
            "TakenBy        CHAR(20)        NOT NULL," \
            "Result         CHAR(20)        NOT NULL," \
            "TimeOfAttempt  INTEGER         NOT NULL," \
            "DateTime       DATETIME        NOT NULL);");
    // Execute SQL statement 
    rc = sqlite3_exec(db, sql, 0, 0, &zErrMsg);
    if( rc != SQLITE_OK )
    {
        fprintf(stderr, "SQL error: %s\n\n", zErrMsg);
        sqlite3_free(zErrMsg);
        return false;
    }
    else
    {
        fprintf(stdout, "\nTest Table created successfully\n");
    }
    cout << endl;
    
    sqlite3_close(db); 
    
    return true;
    
}

